#include "stdafx.h"

#include "symbiandepend.h"

#ifdef __SYMBIAN32__
#include <gdi.h>
#include "TBrCtlObserver.h"
#endif

#include "graphicsproxy.h"
#include "utils.h"
#include "controlcontext.h"

#ifdef WINCE
#pragma warning(disable:4819)
#endif

CGraphicsProxy::CGraphicsProxy(const MControlContext& aParent)
	: iParent(aParent)
	, iInnerGc(NULL)
#ifndef __SYMBIAN32__
	//, m_hTempGc(NULL)
#endif
	, iStoredClipsets(NULL)
	, iTransPoint(0, 0)
	, iFont(NULL)
#ifdef WINCE
	, m_hOldPen(NULL)
	, m_hCurrPen(NULL)
	, m_hOldBrush(NULL)
	, m_hCurrBrush(NULL)
	, m_hOldFont(NULL)
	, m_PenStyle(CGraphicsContext::ESolidPen)
	, m_BrushStyle(CGraphicsContext::ESolidBrush)
	, m_dwPenColor(0)
	, m_dwBrushColor(0)
#endif
{
}

CGraphicsProxy::~CGraphicsProxy()
{
#ifdef WINCE
	if (iInnerGc != NULL)
	{
		if (m_hOldPen != NULL)
		{
			::SelectObject(iInnerGc, m_hOldPen);
			m_hOldPen = NULL;
		}

		if (m_hCurrPen != NULL)
		{
			::DeleteObject(m_hCurrPen);
			m_hCurrPen = NULL;
		}

		if (m_hOldBrush != NULL)
		{
			::SelectObject(iInnerGc, m_hOldBrush);
			m_hOldBrush = NULL;
		}

		if (m_hCurrBrush != NULL)
		{
			::DeleteObject(m_hCurrBrush);
			m_hCurrBrush = NULL;
		}

		if (m_hOldFont != NULL)
		{
			::SelectObject(iInnerGc, m_hOldFont);
			m_hOldFont = NULL;
		}
	}

	//::DeleteDC(m_hTempGc);
#endif

	SAFE_DELETE(iStoredClipsets);
}

CGraphicsProxy* CGraphicsProxy::NewLC(const MControlContext& aParent)
{
	CGraphicsProxy* self = new ELEAVE CGraphicsProxy(aParent);
	CLEANUPSTACK_PUSHL_SELF;
	self->ConstructL();
	return self;
}

CGraphicsProxy* CGraphicsProxy::NewL(const MControlContext& aParent)
{
	CGraphicsProxy* self = CGraphicsProxy::NewLC(aParent);
	CLEANUPSTACK_POP_SELF;
	return self;
}

void CGraphicsProxy::ConstructL()
{
#ifdef __SYMBIAN32__
	iStoredClipsets = new (ELeave) CStack<TRectEx, ETrue>;
	if (iStoredClipsets == NULL)
		User::LeaveNoMemory();
#else
	iStoredClipsets = new std::vector<TRectEx*>;
#endif
}

TBool CGraphicsProxy::SetClipL(TInt aCx, TInt aCy, TInt aCw, TInt aCh)
{
	if (iInnerGc == NULL)
		return EFalse;

	TBool result;
	TInt orgcx;
	TInt orgcy;
	TInt orgcw;
	TInt orgch;

	// 判断栈是否为空
	if (iStoredClipsets->ARRAYISEMPTY())
	{
		orgcx = 0;
		orgcy = 0;
		orgcw = iParent.RectRegion().Width();
		orgch = iParent.RectRegion().Height();
	}
	else
	{
		TRectEx* orc = 
#ifdef __SYMBIAN32__
			iStoredClipsets->Head();
#else
			(*iStoredClipsets)[iStoredClipsets->size() - 1];
#endif

		if (orc != NULL)
		{
			orgcx = orc->iTl.iX;
			orgcy = orc->iTl.iY;
			orgcw = orc->Width();
			orgch = orc->Height();
		}
		else
		{
			orgcx = 0;
			orgcy = 0;
			orgcw = iParent.RectRegion().Width();
			orgch = iParent.RectRegion().Height();
		}
	}

	// 计算原Clip区域与当前区域的交叉区域并截取Clip
	//TRectEx cr = TRectEx::Intersect(orgcx, orgcy , orgcw, orgch
	//	, aCx, aCy, aCw, aCh);
	TRect cr = TRect(orgcx, orgcy, orgcx + orgcw, orgcy + orgch);
	TRect cy = TRect(aCx, aCy, aCx + aCw, aCy + aCh );
	cr.Intersection(cy);

	if (cr.Width() > 0 && cr.Height() > 0) 
	{
#ifdef __SYMBIAN32__
		iInnerGc->CancelClippingRect();
		iInnerGc->SetClippingRect(cr);
#else
		::SelectClipRgn(iInnerGc, NULL);
		::IntersectClipRect(iInnerGc
							, cr.iTl.iX + iTransPoint.iX
							, cr.iTl.iY + iTransPoint.iY
							, cr.iBr.iX + iTransPoint.iX
							, cr.iBr.iY + iTransPoint.iY);
#endif

		TRectEx* storedClip = new TRectEx(cr);

#ifdef __SYMBIAN32__
		if (!storedClip)
			User::LeaveNoMemory();

		CleanupStack::PushL(storedClip);
		iStoredClipsets->PushL(storedClip);
		CleanupStack::Pop(storedClip);
#else
		iStoredClipsets->push_back(storedClip);
#endif
		
		result = ETrue;
	} 
	else
		result = EFalse;

	return result;
}

void CGraphicsProxy::RestoreClip()
{
#ifdef __SYMBIAN32__
	iInnerGc->CancelClippingRect();
	if (!iStoredClipsets->IsEmpty()) 
	{
		TRectEx* storedClip = iStoredClipsets->Pop();
		SAFE_DELETE(storedClip);

		if (iStoredClipsets->IsEmpty())
			iInnerGc->SetClippingRect(iParent.RectRegion());
		else
		{
			storedClip = iStoredClipsets->Head();
			iInnerGc->SetClippingRect(*storedClip);
		}
	}
#else
	::SelectClipRgn(iInnerGc, NULL);

	if (!iStoredClipsets->empty()) 
	{
		TRectEx* storedClip = (*iStoredClipsets)[iStoredClipsets->size() - 1];
		iStoredClipsets->pop_back();

		SAFE_DELETE(storedClip);

		if (iStoredClipsets->empty())
		{
			//iInnerGc->SetClippingRect(iParent.RectRegion());
			::IntersectClipRect(iInnerGc
								, iParent.RectRegion().iTl.iX + iTransPoint.iX
								, iParent.RectRegion().iTl.iY + iTransPoint.iY
								, iParent.RectRegion().iBr.iX + iTransPoint.iX
								, iParent.RectRegion().iBr.iY + iTransPoint.iY);
		}
		else
		{
			storedClip = (*iStoredClipsets)[iStoredClipsets->size() - 1];
			//iInnerGc->SetClippingRect(*storedClip);
			::IntersectClipRect(iInnerGc
								, storedClip->iTl.iX + iTransPoint.iX
								, storedClip->iTl.iY + iTransPoint.iY
								, storedClip->iBr.iX + iTransPoint.iX
								, storedClip->iBr.iY + iTransPoint.iY);
		}
	}
#endif
}

void CGraphicsProxy::Translate(TInt x, TInt y)
{
	iTransPoint.iX += x;
	iTransPoint.iY += y;

#ifdef __SYMBIAN32__
	iInnerGc->SetOrigin(iTransPoint);
#endif

	for (TInt n = 0; n < (TInt) iStoredClipsets->ARRAYCOUNT(); ++n)
	{
		TRectEx* rect = (*iStoredClipsets)[n];
		rect->Move(-x, -y);
	}
}
